package com.example.thread.case4;

import java.util.*;
import java.util.concurrent.*;

public class Test {

    // 传统并发容器
    public static Map m = Collections.synchronizedMap(new HashMap<String, String>());
    public static List<String> l = Collections.synchronizedList(new LinkedList<String>());

    /**
     * CAS入队(tail)出队(head)
     */
    ConcurrentLinkedQueue<String> clq = new ConcurrentLinkedQueue<String>();


    public static SynchronousQueue sq = new SynchronousQueue();



    
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        l.add("test1");
        m.put("code","001");
        System.out.println(l);
        System.out.println(m);

        ExecutorService e = Executors.newFixedThreadPool(10);
        Future f = e.submit(new CallableTask());
        Future f1 = e.submit(new CallableTask());
        System.out.println(f.get());
        System.out.println(f1.get());
        e.shutdown();

        FutureTask tr = new FutureTask(new CallableTask());
        Thread t2 = new Thread(tr);
        t2.setName("my01");
        t2.start();
        System.out.println(tr.get());

        SynchronousQueue<Integer> queue = new SynchronousQueue<Integer>();
        SynchronousProducers demo2 = new SynchronousProducers(queue);
        ConsumersProducers demo1 = new ConsumersProducers(queue);
        Thread ts1= new Thread(demo2);
        Thread ts2= new Thread(demo1);
        ts1.start();
        ts2.start();
    }

    /**
     * 携带结果的异步任务
     * Callable和Runnable的区别如下：
     * Callable定义的方法是call，而Runnable定义的方法是run。
     * Callable的call方法可以有返回值，而Runnable的run方法不能有返回值。
     * Callable的call方法可抛出异常，而Runnable的run方法不能抛出异常。
     */
    public static class CallableTask implements Callable<String>{
        @Override
        public String call() throws Exception {
            return "hello callable"+Thread.currentThread().getName();
        }
    }

    public static class SynchronousProducers implements Runnable{

        SynchronousQueue<Integer> queue = null;

        public SynchronousProducers(SynchronousQueue<Integer> queue){
            this.queue = queue;
        }

        @Override
        public void run() {
            int rand = new Random().nextInt(1000);
            System.out.println(String.format("模拟生产者：%d",rand));
            try{
                TimeUnit.SECONDS.sleep(3);
                queue.put(rand);
            }catch(Exception e){
                e.printStackTrace();
            }
            System.out.println(queue.isEmpty());
        }
    }

    public static class ConsumersProducers implements Runnable{

        SynchronousQueue<Integer> queue = null;

        public ConsumersProducers(SynchronousQueue<Integer> queue){
            this.queue = queue;
        }

        @Override
        public void run() {
            System.out.println("消费者已经准备好接受元素了...");
            try{
                System.out.println(String.format("消费一个元素：%d", queue.take()));
            }catch(Exception e){
                e.printStackTrace();
            }

        }
    }

}
